#include "code/inc/lcd_protocol.h"
#include "dev/mem.h"
#include "string.h"
#include "stdio.h"
typedef void (pro_send)(char *buf);

typedef void (*lcdrecvdeal)(char *paraStr,void *promsg);
typedef void (*lcdackdeal)(void *promsg);

struct t_cmdinfo {
    char *cmd;
    lcdrecvdeal func;
};
struct t_cmdackinfo {
    char *cmd;
    lcdackdeal func;
};

struct promsg
{
   uint8 guiinitackstate;//初始化有没有应答标志位
   uint8 timesyncackstate;//时钟同步信号有无应答标志位
   pro_send *prosend;//向上层递交信息

   uint8 guiinitstate; //协议层有无初始化标志位
   struct t_proinitmsg initmsg;
};

static struct promsg _promsg;

#define PROSEND(P,DATA) if(P){P(DATA);}

struct Item {
    char *begin;
    uint32 len;
    char *next;
};


static void GetCmdItem(const char *buf, const char *delim, struct Item *item) {
    char *end;
    if (item->begin == NULL) {
        item->begin = (char *)buf;
    } else if (item->next != NULL) {
        item->begin = item->next;
    }
    item->begin += strspn((const char *)item->begin, delim);
    if (*item->begin == '\0') {
        item->len = 0;
        return;
    }

    end = strpbrk((const char *)item->begin, delim);
    if (end == NULL) {
        item->next = strchr(item->begin, '\0');
        item->len = (uint32)(item->next - item->begin);
    } else {
        item->next = end + 1;
        item->len = (uint32)(end - item->begin);
    }
}

void GetCmdStr( char *buf, const char *cmd, char *value, int len){
    struct Item item = {0};
    GetCmdItem(buf, "&", &item);
    while(item.len != 0) {
        struct Item itemcmd = {0};
        GetCmdItem(item.begin, "=", &itemcmd);
        if (itemcmd.len != 0 && (strlen(item.next) == 0 || itemcmd.next < (item.next - 1)) && itemcmd.len == strlen(cmd)
                && strncmp(cmd, itemcmd.begin, itemcmd.len) == 0) {
            uint32 l = (((item.len - strlen(cmd)) - 1) >= (uint32)len) ? ((uint32)len - 1) : ((item.len - strlen(cmd)) - 1);
            strncpy(value, itemcmd.next, l);
            return;
        }
        GetCmdItem(buf, "&", &item);
    }
}
static char* Getkeyvalue(char *buf,struct keyvaluepair *pair)
{
    struct Item item = {0};
    GetCmdItem(buf, "&", &item);

    char tmp[30] = {0};
    strncpy(tmp,item.begin,item.len);

    if(!item.len)
    {
        return 0;
    }
    char *demi = "=";
    char *token;

    token = strtok(tmp,demi);
    sprintf(pair->key,"%s",token);

    token = strtok(NULL,demi);
    sprintf(pair->value,"%s",token);

    return item.next;
}

static uint8 StrEqual(const char *src, const char *dst) {
    return (strncmp(src, dst, strlen(dst)) == 0);
}

static void AddStrStr(char *str, const char *cmd, const char *value) {
    strcat(str, cmd);
    strcat(str, value);
}

static void lcdprotintf_guiinit(char *msg,void *promsg)
{
   struct promsg *p = (struct promsg *)promsg;

   char cmd[30] = {0};
   char dev_ver[30] = {0};
   char pro_ver[30] = {0};
   char dev_type[30] = {0};
   char dev_num[30] = {0};
   char gun_num[30] = {0};
   GetCmdStr(msg, "cmd", cmd,sizeof(cmd));
   GetCmdStr(msg, "dev_ver", dev_ver,sizeof(dev_ver));
   GetCmdStr(msg, "pro_ver", pro_ver,sizeof(pro_ver));
   GetCmdStr(msg, "dev_type",dev_type,sizeof(dev_type));
   GetCmdStr(msg, "dev_num", dev_num,sizeof(dev_num));
   GetCmdStr(msg, "gun_num", gun_num,sizeof(gun_num));

   sprintf(p->initmsg.devver,"%s",dev_ver);
   sprintf(p->initmsg.prover,"%s",pro_ver);
   sprintf(p->initmsg.devtype,"%s",dev_type);
   sprintf(p->initmsg.devnum,"%s",dev_num);
   sprintf(p->initmsg.gunnum,"%s",gun_num);

   p->guiinitackstate = 1;
   p->guiinitstate = 1;
}

static void lcdprotintf_guiupdate(char *msg,void *promsg)
{
   char cmd[30] = {0};
   char gunno[30] = {0};
   char type[30] = {0};
   char comment[256] = {0};

   GetCmdStr(msg, "cmd", cmd,sizeof(cmd));
   GetCmdStr(msg, "gunno", gunno,sizeof(gunno));
   GetCmdStr(msg, "type", type,sizeof(type));
   GetCmdStr(msg, "comment",comment,sizeof(comment));

   mem_setscreenmsg(gunno,type,comment);
}

static void lcdprotintf_guiinitack(void *msg)
{
   struct promsg *p = (struct promsg *)msg;
   if(!p->guiinitackstate)
   {
       return;
   }
   char ack[256] = {0};
   char guiver[20] = {0};
   if(!mem_getguiver(guiver))
   {
       return ;
   }

   AddStrStr(ack,"cmd=","guiinit_ack");
   AddStrStr(ack,"&gui_ver=",guiver);
   AddStrStr(ack,"&pro_ver=",PRO_VER);
   AddStrStr(ack,"&flag=","succ");

   PROSEND(p->prosend,ack);
   p->guiinitackstate = 0;

   mem_initgui(&p->initmsg);
}

static void lcdprotintf_timesync(char *msg,void *promsg)
{
  struct promsg *p = (struct promsg *)promsg;
  char cmd[30] = {0};
  char time[30] = {0};
  char opera[30] = {0};

  GetCmdStr(msg, "cmd", cmd,sizeof(cmd));
  GetCmdStr(msg, "time", time,sizeof(time));
  GetCmdStr(msg, "opera", opera,sizeof(opera));

  if(StrEqual("toset",opera))//设置gui RTC
  {
     mem_setrtc(time);
  }
  else if(StrEqual("toget",opera))//拿取rtc时间
  {
      p->timesyncackstate = 1;
  }
}
static void lcdprotintf_devyx(char *msg,void *promsg)
{
    char cmd[30] = {0};
    char gunno[30] = {0};
    struct t_prodevyx devyx = {0};

    GetCmdStr(msg, "cmd", cmd,sizeof(cmd));
    GetCmdStr(msg, "gunno", gunno,sizeof(gunno));
    GetCmdStr(msg, "gunstate", devyx.gunstate,sizeof(devyx.gunstate));
    GetCmdStr(msg, "connectstate", devyx.connectstate,sizeof(devyx.connectstate));
    GetCmdStr(msg, "netstate", devyx.netstate,sizeof(devyx.netstate));

    mem_updatedevyx(gunno,&devyx);

}
static void lcdprotintf_devyc(char *msg,void *promsg)
{
    char cmd[30] = {0};
    char gunno[30] = {0};
    struct t_prodevyc devyc = {0};

    GetCmdStr(msg, "cmd", cmd,sizeof(cmd));
    GetCmdStr(msg, "gunno", gunno,sizeof(gunno));
    GetCmdStr(msg, "yctype", devyc.yctype,sizeof(devyc.yctype));
    GetCmdStr(msg, "charingtime", devyc.charingtime,sizeof(devyc.charingtime));
    GetCmdStr(msg, "chargingpower", devyc.chargingpower,sizeof(devyc.chargingpower));
    GetCmdStr(msg, "outputvoltage", devyc.outputvoltage,sizeof(devyc.outputvoltage));
    GetCmdStr(msg, "outputcurrent", devyc.outputcurrent,sizeof(devyc.outputcurrent));
    GetCmdStr(msg, "outputkwh", devyc.outputkwh,sizeof(devyc.outputkwh));
    GetCmdStr(msg, "devstate", devyc.devstate,sizeof(devyc.devstate));
    GetCmdStr(msg, "chargingpoingmsg", devyc.chargingpoingmsg,sizeof(devyc.chargingpoingmsg));
    GetCmdStr(msg, "demandvoltage", devyc.demandvoltage,sizeof(devyc.demandvoltage));
    GetCmdStr(msg, "demandcurrent", devyc.demandcurrent,sizeof(devyc.demandcurrent));
    GetCmdStr(msg, "remaintime", devyc.remaintime,sizeof(devyc.remaintime));
    GetCmdStr(msg, "soc", devyc.soc,sizeof(devyc.soc));
    GetCmdStr(msg, "elecpcs", devyc.elecpcs,sizeof(devyc.elecpcs));
    GetCmdStr(msg, "serverpcs", devyc.serverpcs,sizeof(devyc.serverpcs));
    GetCmdStr(msg, "eleccost", devyc.eleccost,sizeof(devyc.eleccost));
    GetCmdStr(msg, "servercost", devyc.servercost,sizeof(devyc.servercost));
    GetCmdStr(msg, "totalcost", devyc.totalcost,sizeof(devyc.totalcost));
    GetCmdStr(msg, "settlepower", devyc.settlepower,sizeof(devyc.settlepower));
    GetCmdStr(msg, "settlecost", devyc.settlecost,sizeof(devyc.settlecost));
    GetCmdStr(msg, "settletime", devyc.settletime,sizeof(devyc.settletime));
    GetCmdStr(msg, "alarminfo", devyc.alarminfo,sizeof(devyc.alarminfo));

    mem_updatedevyc(gunno,&devyc);
}
static void lcdprotintf_startauth(char *msg,void *promsg)
{
   struct t_startauth auth = {0};
   char cmd[30] = {0};
   char gunno[30] = {0};

   GetCmdStr(msg, "cmd", cmd,sizeof(cmd));
   GetCmdStr(msg, "gunno", gunno,sizeof(gunno));

   GetCmdStr(msg, "authtype", auth.authtype,sizeof(auth.authtype));
   GetCmdStr(msg, "cardno", auth.cardno,sizeof(auth.cardno));
   GetCmdStr(msg, "pwdtype", auth.pwdtype,sizeof(auth.pwdtype));
   GetCmdStr(msg, "flag", auth.flag,sizeof(auth.flag));
   GetCmdStr(msg, "failreason", auth.failreason,sizeof(auth.failreason));

   mem_startauth(gunno,&auth);
}
static void lcdprotintf_timesyncack(void *msg)
{
    struct promsg *p = (struct promsg *)msg;
    if(!p->timesyncackstate)
    {
        return ;
    }

    char ack[256] = {0};
    char time[50] = {0};

    int ret = mem_getrtc(time);
    if(!ret)
    {
        return;
    }
    AddStrStr(ack,"cmd=","timesync_ack");
    AddStrStr(ack,"&time=",time);
    AddStrStr(ack,"&opera=","toget");
    AddStrStr(ack,"&flag=","succ");

    PROSEND(p->prosend,ack);
    p->timesyncackstate = 0;
}
static void lcdprotintf_guiyx(void *msg)
{

}

static void lcdprotintf_guiyc(void *msg)
{

}

static void lcdprotintf_guiyk(void *msg)
{
  struct promsg *p = (struct promsg *)msg;
  struct t_prodevyk yk = {0};

  uint8 ret = mem_getyk(&yk);
  if(!ret)
  {
      return ;
  }
  char ack[256] = {0};
  AddStrStr(ack,"cmd=","gui_yk");
  AddStrStr(ack,"&gunno=",yk.gunno);
  AddStrStr(ack,"&yk_type=",yk.yk_type);
  AddStrStr(ack,"&start_type=",yk.start_type);
  AddStrStr(ack,"&start_value=",yk.start_value);

  PROSEND(p->prosend,ack);
}

static void lcdprotintf_pwdauth(void *msg)
{
  struct promsg *p = (struct promsg *)msg;
  struct t_pwdauth auth = {0};
  uint8 ret = mem_getpwdauth(&auth);
  if(!ret)
  {
    return ;
  }
  char ack[256] = {0};
  AddStrStr(ack,"cmd=","pwdauth");
  AddStrStr(ack,"&gunno=",auth.gunno);
  AddStrStr(ack,"&type=",auth.type);
  AddStrStr(ack,"&cardno=",auth.cardno);
  AddStrStr(ack,"&password=",auth.password);

  PROSEND(p->prosend,ack);
}
static void lcdprotintf_pwdauth_ack(char *msg,void *promsg)
{
   char cmd[30] = {0};
   char gunno[30] = {0};
   struct t_pwdauthack auth = {0};

   GetCmdStr(msg, "cmd", cmd,sizeof(cmd));
   GetCmdStr(msg, "gunno",gunno,sizeof(gunno));
   GetCmdStr(msg, "type", auth.type,sizeof(auth.type));
   GetCmdStr(msg, "cardno",auth.cardno,sizeof(auth.cardno));
   GetCmdStr(msg, "password", auth.password,sizeof(auth.password));
   GetCmdStr(msg, "flag", auth.flag,sizeof(auth.flag));
	 
   mem_pwdauthack(gunno,&auth);
}

static void lcdprotintf_filecheck(void *msg)
{
    struct promsg *p = (struct promsg *)msg;
    struct t_filecheck filecheck = {0};
    uint8 ret = mem_getfilecheck(&filecheck);
    if(!ret)
    {
      return ;
    }
    char ack[256] = {0};
    AddStrStr(ack,"cmd=","filecheck");
    AddStrStr(ack,"&filetype=",filecheck.filetype);
    AddStrStr(ack,"&baseno=",filecheck.baseno);
    AddStrStr(ack,"&totalnum=",filecheck.totalnum);

    PROSEND(p->prosend,ack);
}
static void lcdprotintf_filecheck_ack(char *msg,void *promsg)
{
    struct t_filecheckack filecheckack = {0};

    char cmd[50] = {0};
    GetCmdStr(msg, "cmd", cmd,sizeof(cmd));
    GetCmdStr(msg, "filetype", filecheckack.filetype,sizeof(filecheckack.filetype));
    GetCmdStr(msg, "baseno",filecheckack.baseno,sizeof(filecheckack.baseno));
    GetCmdStr(msg, "totalnum", filecheckack.totalnum,sizeof(filecheckack.totalnum));
    GetCmdStr(msg, "readnum", filecheckack.readnum,sizeof(filecheckack.readnum));

    uint32 len = sizeof(filecheckack.keyvaluebuf)/sizeof(struct keyvaluepair);
    char *posbegin = "posbegin";

    char* p = strstr((const char *)msg,posbegin)
            +strlen(posbegin)+1;
    if(!p)
    {
        return ;
    }

    uint32 i = 0;
    for(i = 0;i<len;i++)
    {
      p = Getkeyvalue(p,&filecheckack.keyvaluebuf[i]);
      if(!p)
      {
          break;
      }
    }

    mem_filecheckack(&filecheckack);
}

static void lcdprotintf_filechange(void *msg)
{
    struct promsg *p = (struct promsg *)msg;
    struct  t_filechange filechange = {0};
    uint8 ret = mem_getfilechange(&filechange);
    if(!ret)
    {
      return ;
    }
    char ack[256] = {0};
    AddStrStr(ack,"cmd=","file_change");
    AddStrStr(ack,"&filetype",filechange.filetype);
    AddStrStr(ack,"&type=",filechange.type);
    AddStrStr(ack,"&value=",filechange.valuep);

    PROSEND(p->prosend,ack);
}

static void lcdprotintf_err(char *msg,void *promsg)
{
   sprintf(msg,"lcdprotintf_err ");
}

static const struct t_cmdinfo g_cmdinfo[] = {
    {"guiinit",     lcdprotintf_guiinit},
    {"gui_update",  lcdprotintf_guiupdate},
    {"timesync",    lcdprotintf_timesync},
    {"dev_yx",      lcdprotintf_devyx},
    {"dev_yc",      lcdprotintf_devyc},
    {"start_auth",  lcdprotintf_startauth},
    {"pwdauth_ack", lcdprotintf_pwdauth_ack},
    {"filecheck_ack",lcdprotintf_filecheck_ack},
};

static const struct t_cmdackinfo g_cmdackinfo[] = {
    {"guiinit_ack",    lcdprotintf_guiinitack},
    {"timesync_ack",    lcdprotintf_timesyncack},
    {"gui_yx",      lcdprotintf_guiyx},
    {"gui_yc",      lcdprotintf_guiyc},
    {"gui_yk",      lcdprotintf_guiyk},
    {"pwdauth", lcdprotintf_pwdauth},
    {"filecheck", lcdprotintf_filecheck},
    {"file_change", lcdprotintf_filechange},
};

static lcdrecvdeal getlcdcmddeal(const char *cmd) {
    uint32 i = 0;
    uint32 len = sizeof(g_cmdinfo)/sizeof(struct t_cmdinfo);
    for(i = 0;i<len;i++)
    {
        if(StrEqual(cmd, g_cmdinfo[i].cmd) )
        {
            return g_cmdinfo[i].func;
        }
    }
    return lcdprotintf_err ;
}

static void  protocolack_poll(void)
{

    uint32 i = 0;

    if(!_promsg.guiinitstate)
    {
        return ;
    }
    for(i=0;i<sizeof(g_cmdackinfo)/sizeof(struct t_cmdackinfo);i++)
    {
        g_cmdackinfo[i].func((void *)&_promsg);
    }
}
void  protocol_dealmsg(const char *src)
{
    char cmd[32] = {0};
    GetCmdStr((char *)src, "cmd", cmd,sizeof(cmd));
    if(!strlen(cmd))
    {
      return ;
    }
    lcdrecvdeal p = NULL;
    p = getlcdcmddeal(cmd);
    if(!p)
    {
      return ;
    }
    p((char *)src,(void *)&_promsg);

}
void protocol_poll(void)
{
   mem_poll();
   protocolack_poll();
}

void protocol_init(void *callback_prosend)
{
    memset((uint8 *)&_promsg,0,sizeof(_promsg));
     mem_init();
    _promsg.prosend = (pro_send *)callback_prosend;
}
